/*
 * Copyright (C) 2015-2021 Alibaba Group Holding Limited
 */

#include <stdio.h>
#include <stdlib.h>
#include <ulog/ulog.h>
#include <dirent.h>
#include "record.h"
#include "cx_debug.h"
#include "cx_hal.h"
#include "cx_utility.h"

#define TAG "cxsnapshot"

int cx_vr_snapshot(void *hdl, int cam_id, uint8_t image_name[MAX_RECORD_NAME_LEN])
{
    (void)cam_id;
    CHECK_PARAM(hdl && image_name, -1);
    
    cx_raw_img_type_e type;
    int width, height;
    int ret;
    char device_id[128];
    static char pic_buff[360 * 640 * 4];

    cx_record_priv_t *priv = (cx_record_priv_t *)hdl;
#ifdef CX_VR_LOWEST_STORAGE
    int free_percent;
    struct statfs fsinfo;
    ret = statfs(priv->root_path, &fsinfo);
    if (ret == 0) {
        free_percent = (int)((double)fsinfo.f_bfree * 100 / fsinfo.f_blocks);
        if (free_percent < CX_VR_LOWEST_STORAGE) {
            LOGE(TAG, "no enough room %d%%", free_percent);
            return -1;
        }
    }
#endif
    ret = cx_get_raw_image(0, pic_buff, &type, &width, &height);
    CHECK_RET_WITH_RET(ret >0 && type == CX_IMAGE_FORMAT_BGRA && ret == width * height * 4, -1);

	extern void rgba_to_jpeg(unsigned char *imageData,
                    unsigned char **compressedBuffer,
                    int imageWidth,
                    int imageHeight,
                    int channels,
                    unsigned long *outSize);

    unsigned long outSize = 0;
	unsigned char *jpgoutput = NULL;
	rgba_to_jpeg((unsigned char *)pic_buff, &jpgoutput, 360, 640, 4, &outSize);
	// printf("after jpeg convert, mem=%p outsize=%d\n", jpgoutput, outSize);

    char str_path[128];
    char str_time[13];
    char str_date[7] = {0};

    /* check path /root/pic/ */
    snprintf(str_path, 128, "%s/picture", priv->root_path);
    if (access(str_path, 0) != 0) {
        mkdir(str_path, 755);
    }

    /* check path /root/pic/yyMMdd/ */
    cx_util_localtime_print(str_time);
    memcpy(str_date, str_time, 6);
    snprintf(str_path, 128, "%s/%s", str_path, str_date);
    if (access(str_path, 0) != 0) {
        mkdir(str_path, 755);
    }
    cx_get_device_id(device_id);
    snprintf(str_path, 128, "%s/pic_%s_%s.jpg", str_path, device_id, str_time);
    printf("snapshot time=%s date=%s path=%s\n", str_time, str_date, str_path);
    strncpy((char *)image_name, str_path, MAX_RECORD_NAME_LEN);

    FILE *file = fopen(str_path, "wb");
    size_t n = fwrite(jpgoutput, 1, (size_t)outSize, file);
    if (n < (size_t)outSize) {
        LOGE(TAG, "snapshot write error n=%u", n);
    }

    fclose(file);
    free(jpgoutput);

    return 0;
}

int cx_vr_snapshot_search(void *hdl, uint32_t start_time, uint32_t stop_time, cx_vr_snapshot_info_t *images, int num)
{
    int ret;
    int pic_num = 0;
    int pic_size;
    char pic_type[10];
    long long  pic_identity;
    int pic_year, pic_mon, pic_day, pic_hour, pic_min, pic_sec;
    uint32_t pic_time;
    struct tm *tm;
    char check_dir_name[MAX_RECORD_NAME_LEN];
    uint32_t relative_start_time, relative_stop_time;

    CHECK_PARAM(hdl && (start_time < stop_time) && images && (num >= 0), -1);
    cx_record_priv_t *priv = (cx_record_priv_t *)hdl;

    /* utc时间转化 */
    time_t time_tran = start_time;
    tm = localtime(&time_tran);
    cx_util_utc_to_beijing(tm);

    uint32_t start_time_cur_day = start_time - tm->tm_hour*3600 - tm->tm_min*60 - tm->tm_sec;
    if((stop_time - start_time_cur_day) >= 24*60*60) {
        LOGE(TAG, "start_time stop_time not in one day");
        return -1;
    }

    relative_start_time = tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
    time_tran = stop_time;
    tm = localtime(&time_tran);
    cx_util_utc_to_beijing(tm);
    relative_stop_time = tm->tm_hour * 3600 + tm->tm_min * 60 + tm->tm_sec;
    sprintf(check_dir_name, "%s/picture/%02d%02d%02d", priv->root_path, tm->tm_year-2000, tm->tm_mon, tm->tm_mday);

    DIR *dp;
    struct dirent *out_dirent;
    char *destination = (char *)malloc(MAX_RECORD_NAME_LEN);
    dp = (DIR *)opendir(check_dir_name);

    if(!dp){
        LOGD(TAG, "current interval no picture");
        return 0;
    }
    LOGD(TAG, "*********************snap shot info*******************");
    LOGD(TAG, "check directory %s", check_dir_name);
    while (1) {
        out_dirent = readdir(dp);
        if(!out_dirent){
            break;
        }
        ret = sscanf(out_dirent->d_name, "pic_%llx_%2d%2d%2d%2d%2d%2d.%s", &pic_identity, &pic_year, &pic_mon, &pic_day, &pic_hour, &pic_min, &pic_sec, pic_type);
        if(ret == 8) {
            pic_time = pic_hour * 3600 + pic_min * 60 + pic_sec + start_time - relative_start_time;
            if((pic_time >= start_time) && (pic_time <= stop_time)) {
                strncpy(destination, check_dir_name, MAX_RECORD_NAME_LEN);
                strcat(destination, "/");
                strcat(destination, out_dirent->d_name);
                FILE *fp = fopen(destination, "r");
                if(!fp)
                    continue;
                fseek(fp, 0, SEEK_END);
                pic_size = ftell(fp);
                fclose(fp);
                LOGD(TAG, "picture:%d %s start_time:%d size:%d", pic_num, out_dirent->d_name, pic_time, pic_size);
                strncpy(images[pic_num].name, destination, MAX_RECORD_NAME_LEN);
                images[pic_num].size = pic_size;
                images[pic_num].time = pic_time;
                if(strcmp(pic_type, "jpg") == 0) {
                    images[pic_num].type = CX_PIC_FORMAT_JPEG;
                } else if(strcmp(pic_type, "png") == 0) {
                    images[pic_num].type = CX_PIC_FORMAT_PNG;
                } else if(strcmp(pic_type, "bmp") == 0) {
                    images[pic_num].type = CX_PIC_FORMAT_BMP;
                } else {
                    images[pic_num].type = CX_PIC_FORMAT_UNKNOWN;
                }
                pic_num++;
                if(pic_num >= num) {
                    break;
                }
            }
        } else {
            LOGE(TAG, "%s format error %d", out_dirent->d_name, ret);
        }
    }
    LOGD(TAG, "*********************snap shot info*******************");
    closedir(dp);
    free(destination);
    return pic_num;
}

int cx_vr_snapshot_get(void *hdl, uint8_t image_name[MAX_RECORD_NAME_LEN], uint8_t *image, uint32_t offset, int max_size)
{
    int ret;
    int file_size;
    unsigned int move_offset = 0;

    CHECK_PARAM(hdl && image_name && image, -1);
    FILE *fp = fopen((char *)image_name, "r");
    if(!fp) {
        LOGE(TAG, "file %s error");
        return -1;
    }
    fseek(fp, 0, SEEK_END);
    file_size = ftell(fp);
    if((file_size - offset) > max_size) {
        LOGE(TAG, "file size too big (%d - %d)>%d", file_size, offset, max_size);
        fclose(fp);
        return -1;
    }
    LOGD(TAG, "file %s size:%d offset:%d\n", image_name, file_size, offset);
    fseek(fp, offset, SEEK_SET);
    while(!feof(fp)) {
        ret = fread(image + move_offset, 1, 1024, fp);
		move_offset+=ret;
    }
    return 0;
}
